/**
 * 
 */
package com.iss.card.view.store;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.Adapter;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.iss.card.cache.BitmapConfig;
import com.iss.card.cache.ImageDataManager;
import com.iss.card.common.ApplicationManager;
import com.iss.card.model.MarkedProductDetailInfo;
import com.iss.card.view.overrideview.IOnItemSelectedListener;
import com.iss.card.view.overrideview.ScrollViewRefresh.IOnScrollChangedListener;

/**
 * @author dtdh
 * 
 */
public class StoreListViewContainer extends LinearLayout implements
		IOnScrollChangedListener {
	private final static String TAG = StoreListViewContainer.class
			.getSimpleName();
	private final static int BUFFERED_MAX_VIEW = 2;
	private Context mContext = null;
	private Adapter mAdapter = null;
	private List<View> mViews = new ArrayList<View>();
	private int mHeight = 0;
	private int mCurrentPosition = 0;
	private IOnItemSelectedListener mOnItemSelectedListener = null;

	/**
	 * @param context
	 */
	public StoreListViewContainer(Context context) {
		super(context);
		mContext = context;
		init();
	}

	/**
	 * @param context
	 * @param attrs
	 */
	public StoreListViewContainer(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		init();
	}

	/**
	 * set this container's height. this function should be called before
	 * Adapter's {@link #notifyDataSetChanged}.
	 * 
	 * @param h
	 *            height for this container.
	 */
	public void setHeight(int h) {
		mHeight = h;
		Log.d(TAG, "setHeight: h=" + mHeight);
	}

	public void setOnItemSelectedListener(IOnItemSelectedListener l) {
		mOnItemSelectedListener = l;
	}

	public void removeOnItemSelectedListener() {
		mOnItemSelectedListener = null;
	}

	public void setAdapter(Adapter ad) {
		if (mAdapter != null && mObserver != null) {
			mAdapter.unregisterDataSetObserver(mObserver);
		}
		mAdapter = ad;
		mAdapter.registerDataSetObserver(mObserver);
	}

	public Adapter getAdapter() {
		return mAdapter;
	}

	public void onScrollChanged(int l, int t, int oldl, int oldt) {
		final int curPos = findViewPositionByVerticalCoordinate(t);
		Log.d(TAG, "onScrollChanged: " + l + ", " + t + ", oldl=" + oldl
				+ ", oldt=" + oldt + ", height=" + mHeight + ", curRow=" + curPos + ", preRow=" + mCurrentPosition);
		if (t > oldt) { // down.
			if (curPos != mCurrentPosition) {
				mCurrentPosition = curPos;
				setViewVisibleByPosition(mCurrentPosition + 1, true);
				setViewVisibleByPosition(mCurrentPosition - BUFFERED_MAX_VIEW,
						false);
			}
		} else { // up.
			if (curPos != mCurrentPosition) {
				// for Adapter container footer and header so minus 2 to get  the number of store item.
				if(curPos == mAdapter.getCount() - 2){
					mCurrentPosition = curPos;
					setViewVisibleByPosition(mCurrentPosition - 1, true);
				} else {
					mCurrentPosition = curPos;
					setViewVisibleByPosition(mCurrentPosition - 1, true);
					setViewVisibleByPosition(mCurrentPosition + BUFFERED_MAX_VIEW,
							false);
				}
			
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.view.View#onDetachedFromWindow()
	 */
	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		if (mAdapter != null) {
			mAdapter.unregisterDataSetObserver(mObserver);
		}
		clearAllSubviews();
	}

	private DataSetObserver mObserver = new DataSetObserver() {

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.database.DataSetObserver#onChanged()
		 */
		@Override
		public void onChanged() {
			Log.d(TAG, "onChanged");
			super.onChanged();
			final int size = mAdapter.getCount();
			clearAllSubviews();
			LinearLayout.LayoutParams parameter = new LinearLayout.LayoutParams(
					LayoutParams.MATCH_PARENT,
					(mHeight == 0 ? LayoutParams.MATCH_PARENT : mHeight));

			mViews.clear();
			for (int i = 0; i < size; ++i) {
				View v = mAdapter.getView(i, null, null);
				v.setLayoutParams(parameter);
				final int position = i;
				v.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						if (mOnItemSelectedListener != null) {
							mOnItemSelectedListener.OnItemSelected(
									StoreListViewContainer.this, v, position,
									mAdapter.getItem(position));
						}
					}
				});

				addSubView(v, i);
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.database.DataSetObserver#onInvalidated()
		 */
		@Override
		public void onInvalidated() {
			Log.d(TAG, "onInvalidated");
			// TODO Auto-generated method stub
			super.onInvalidated();
		}

	};

	private void init() {
		this.setOrientation(LinearLayout.VERTICAL);
	}

	private void clearAllSubviews() {
		this.removeAllViews();
	}

	private void addSubView(View v, int position) {
		StoreModel info = (StoreModel) mAdapter.getItem(position);
		if (position <= BUFFERED_MAX_VIEW) {
			final int w = ApplicationManager.SCREEN_WIDTH;
			final int picW = Integer.valueOf(info.getPicWidth());
			final int picH = Integer.valueOf(info.getPicHeight());
			ImageDataManager.instance().loadBitmap(info.getPicUrl(),
					(RecycleableImageView) ((LinearLayout) v).getChildAt(0),
					new BitmapConfig(w, (picH * w / picW)));
		}
		mViews.add(v);
		this.addView(v, position);
	}

	private void setViewVisibleByPosition(int pos, boolean isVisible) {
		Log.d(TAG, "setViewVisibleByPosition: pos=" + pos + ", isVisible="
				+ isVisible);
		final int maxPos = mAdapter.getCount() - 1;
		pos = pos > 0 ? pos : 0;
		pos = pos > maxPos ? maxPos : pos;
		setViewVisible(findViewByPosition(pos), mAdapter.getItem(pos),
				isVisible);
	}

	private void setViewVisible(View v, Object item, boolean isVisible) {
		Log.d(TAG, "setViewVisible: v=" + v + ", isVisible=" + isVisible);
		RecycleableImageView img = (RecycleableImageView) ((LinearLayout) v)
				.getChildAt(0);
		if (!isVisible) {
			img.recycleBitmap();
		} else {
			StoreModel info = (StoreModel) item;
			final int w = ApplicationManager.SCREEN_WIDTH;
			final int picW = Integer.valueOf(info.getPicWidth());
			final int picH = Integer.valueOf(info.getPicHeight());
			ImageDataManager.instance().loadBitmap((String) img.getTag(), img,
					new BitmapConfig(w, (picH * w / picW)));
		}
	}

	private int findViewPositionByVerticalCoordinate(int y) {
		// the index for view range from [0, mAdapter.getCount() - 1].
		final int maxY = this.getMeasuredHeight() - 1;
		y = y > maxY ? maxY : y;
		y = y < 0 ? 0 : y;
		return y / mHeight;
	}

	private View findViewByPosition(int pos) {
		View v = (pos < mViews.size() && pos >= 0) ? mViews.get(pos) : null;
		Log.d(TAG, "findViewByPosition: pos = " + pos + ", v=" + v + ", size="
				+ mViews.size());
		return mAdapter.getView(pos, v, null);
	}
}
